﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using Microsoft.WindowsLive.PublishPlugins;

namespace PhotoFramePublishingPlugin
{
// ReSharper disable ClassNeverInstantiated.Global
    public class PublishPlugin : IPublishPlugin
// ReSharper restore ClassNeverInstantiated.Global
    {
        public bool ShowConfigurationSettings(IWin32Window parentWindow, XmlDocument sessionXml, XmlDocument persistXml, IPublishProperties publishProperties)
        {
            var configurationSettingsModel = ConfigurationSettingsModel.FromPersistXml(persistXml);

            var configurationSettingsForm = new ConfigurationSettingsForm(configurationSettingsModel);
            DialogResult result = configurationSettingsForm.ShowDialog(parentWindow);
            if (result != DialogResult.OK)
                return false;

            configurationSettingsModel.WriteToPersistXml(persistXml);
            configurationSettingsModel.WriteToSessionXml(sessionXml);

            return true;
        }

        public bool PublishItem(IWin32Window parentWindow, string mediaObjectId, Stream stream, XmlDocument sessionXml, IPublishProperties publishProperties, IPublishProgressCallback callback, EventWaitHandle cancelEvent)
        {
            ItemDetails itemDetails = SessionHelper.ReadItemDetails(sessionXml, mediaObjectId);
            if (itemDetails.PerceivedType != "image")
                return false;

            string destinationRoot = SessionHelper.ReadDestination(sessionXml);
            if (destinationRoot == null)
                return false;

            Size maxSize = SessionHelper.ReadMaxSize(sessionXml);
            bool shouldAddBorders = SessionHelper.ReadShouldAddBorders(sessionXml);
            Color borderColor = Color.Black;
            bool shouldShortenFilenames = SessionHelper.ReadShouldShortenFileNames(sessionXml);

            string destinationPath = GetDestinationPath(destinationRoot, itemDetails.OriginalFileName, shouldShortenFilenames);

            // TODO: Get Windows Explorer to do the copying, by using IFileOperation? This would give us the nice overwrite prompts, etc...
            // See http://msdn.microsoft.com/en-us/library/bb775771(VS.85).aspx for IFileOperation.
            // See http://msdn.microsoft.com/en-us/magazine/cc163304.aspx for a managed wrapper of IFileOperation.
            // See http://msdn.microsoft.com/en-us/library/bb762145(VS.85).aspx for SHCreateShellItemArrayFromDataObject.
            // See http://blogs.msdn.com/oldnewthing/archive/tags/What+a+drag/default.aspx for Raymond's series on virtual drag and drop (i.e. IDataObject).
            // See http://blogs.msdn.com/delay/archive/2009/10/26/creating-something-from-nothing-developer-friendly-virtual-file-implementation-for-net.aspx for a managed implementation of virtual drag-drop.

            // TODO: What if we run out of room?
            // TODO: What if the file exists already?

            using (FileStream destinationStream = File.OpenWrite(destinationPath))
                return PublishItemInternal(shouldAddBorders, borderColor, stream, maxSize.Width, maxSize.Height, destinationStream);
        }

        internal static string GetDestinationPath(string destinationRoot, string originalFileName, bool shouldShortenFilenames)
        {
            if (!shouldShortenFilenames)
                return Path.Combine(destinationRoot, originalFileName);

            string originalFileNameWithoutExtension = Path.GetFileNameWithoutExtension(originalFileName);
            
            string truncatedFileNameWithoutExtension = originalFileNameWithoutExtension
                .Replace(" ", "")
                .Substring(0, 8);

            string truncatedFileName = Path.ChangeExtension(truncatedFileNameWithoutExtension, Path.GetExtension(originalFileName));

            return Path.Combine(destinationRoot, truncatedFileName);
        }

        internal static bool PublishItemInternal(bool shouldAddBorders, Color borderColor, Stream sourceStream, int maxWidth, int maxHeight, Stream destinationStream)
        {
            if (shouldAddBorders)
            {
                using (Image sourceImage = Image.FromStream(sourceStream))
                using (Image destinationImage = new Bitmap(maxWidth, maxHeight, sourceImage.PixelFormat))
                {
                    using (Graphics g = Graphics.FromImage(destinationImage))
                    {
                        Brush borderBrush = new SolidBrush(borderColor);
                        g.FillRectangle(borderBrush, 0, 0, maxWidth, maxHeight);
                        int offsetX = (maxWidth - sourceImage.Width) / 2;
                        int offsetY = (maxHeight - sourceImage.Height) / 2;
                        Rectangle destinationRect = new Rectangle(offsetX, offsetY, sourceImage.Width, sourceImage.Height);
                        Rectangle sourceRect = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height);
                        g.DrawImage(sourceImage, destinationRect, sourceRect, GraphicsUnit.Pixel);
                    }

                    destinationImage.Save(destinationStream, sourceImage.RawFormat);
                }
            }
            else
            {
                StreamHelper.Copy(sourceStream, destinationStream);
            }

            return true;
        }

        public bool HasPublishResults(XmlDocument sessionXml)
        {
            return true;
        }

        public void LaunchPublishResults(XmlDocument sessionXml)
        {
            string destinationRoot = SessionHelper.ReadDestination(sessionXml);
            Process.Start(destinationRoot);
        }

        public bool HasSummaryInformation(XmlDocument sessionXml)
        {
            return false;
        }

        public void ShowSummaryInformation(IWin32Window parentWindow, XmlDocument sessionXml)
        {
            // Nothing
        }
    }
}
